package gui;

import io.Archivo;
import io.Carpeta;
import io.Cliente;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

/**
 *
 * @author Mariano Zapata
 */
public class ModificadorArbol {
    
    private DefaultTreeModel modelo;
    
    public ModificadorArbol(DefaultTreeModel modelo) {
        this.modelo= modelo;
    }
    
    private DefaultMutableTreeNode cargarObjeto(DefaultMutableTreeNode padre, Object o, int indice)
    {
        DefaultMutableTreeNode nodoNuevo= new DefaultMutableTreeNode(o);
        modelo.insertNodeInto(nodoNuevo, padre, indice);
        if (o instanceof Carpeta)
        {
            Carpeta c= (Carpeta) o;
            if (c.poseeHijos())
                this.agregarNodoVacio(nodoNuevo);
        }
        return nodoNuevo;
    }
    
    public void agregarNodoVacio(DefaultMutableTreeNode padre) {
        modelo.insertNodeInto(new DefaultMutableTreeNode("<Vacío>"), padre, 0);
    }
    
    public void vaciarNodo(DefaultMutableTreeNode nodo)
    {
        while (!nodo.isLeaf())
            modelo.removeNodeFromParent((DefaultMutableTreeNode) nodo.getChildAt(0));
    }
    
    public void cargarNodo(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        int pos= 0;
        this.vaciarNodo(nodoPadre);
        List<Carpeta> hijosCarpeta = carpetaPadre.getHijosCarpeta();
        for (Carpeta car : hijosCarpeta) {
            this.cargarObjeto(nodoPadre, car, pos);
            pos+= 1;
        }
        List<Cliente> hijosCliente = carpetaPadre.getHijosCliente();
        for (Cliente cli : hijosCliente) {
            this.cargarObjeto(nodoPadre, cli, pos);
            pos+= 1;
        }
        List<Archivo> hijosArchivo = carpetaPadre.getHijosArchivo();
        for (Archivo arch : hijosArchivo) {
            this.cargarObjeto(nodoPadre, arch, pos);
            pos += 1;
        }
    }
    
    public DefaultMutableTreeNode agregarCarpeta(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        List<Carpeta> carpetas= carpetaPadre.getHijosCarpeta();
        if (nodoPadre.isLeaf())
            return this.cargarObjeto(nodoPadre, carpetas.get(0), 0);
        int cantidadNodos= nodoPadre.getChildCount();
        if (cantidadNodos == 1 && ((DefaultMutableTreeNode) nodoPadre.getChildAt(0)).getUserObject() instanceof String)
            return null;
        for (int k= 0; k < cantidadNodos; k++)
        {
            Carpeta carpetaActual= carpetas.get(k);
            DefaultMutableTreeNode nodoActual= (DefaultMutableTreeNode) nodoPadre.getChildAt(k);
            if (!nodoActual.getUserObject().equals(carpetaActual))
                return this.cargarObjeto(nodoPadre, carpetaActual, k);
        }
        return this.cargarObjeto(nodoPadre, carpetas.get(cantidadNodos), cantidadNodos);
    }
    
    public DefaultMutableTreeNode agregarCliente(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        List<Cliente> clientes= carpetaPadre.getHijosCliente();
        if (nodoPadre.isLeaf())
            return this.cargarObjeto(nodoPadre, clientes.get(0), 0);
        int cantidadNodos= nodoPadre.getChildCount();
        if (cantidadNodos == 1 && ((DefaultMutableTreeNode) nodoPadre.getChildAt(0)).getUserObject() instanceof String)
            return null;
        int cantidadCarpetas= carpetaPadre.getHijosCarpeta().size();
        int iteradorListaClientes= 0;
        for (int k= cantidadCarpetas; k < cantidadNodos; k++)
        {
            Cliente clienteActual= clientes.get(iteradorListaClientes);
            DefaultMutableTreeNode nodoActual= (DefaultMutableTreeNode) nodoPadre.getChildAt(k);
            if (!nodoActual.getUserObject().equals(clienteActual))
                return this.cargarObjeto(nodoPadre, clienteActual, k);
            iteradorListaClientes+= 1;
        }
        int cantidadClientes= clientes.size();
        if (cantidadClientes == 1)
            return this.cargarObjeto(nodoPadre, clientes.get(0), cantidadNodos);
        else
            return this.cargarObjeto(nodoPadre, clientes.get(cantidadClientes - 1), cantidadNodos);
    }
    
    public DefaultMutableTreeNode agregarArchivo(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        List<Archivo> archivos= carpetaPadre.getHijosArchivo();
        if (nodoPadre.isLeaf())
            return this.cargarObjeto(nodoPadre, archivos.get(0), 0);
        int cantidadNodos= nodoPadre.getChildCount();
        if (cantidadNodos == 1 && ((DefaultMutableTreeNode) nodoPadre.getChildAt(0)).getUserObject() instanceof String)
            return null;
        int cantidadCarpetasYClientes= carpetaPadre.getHijosCarpeta().size() + carpetaPadre.getHijosCliente().size();
        int iteradorListaArchivos= 0;
        for (int k= cantidadCarpetasYClientes; k < cantidadNodos; k++)
        {
            Archivo archivoActual= archivos.get(iteradorListaArchivos);
            DefaultMutableTreeNode nodoActual= (DefaultMutableTreeNode) nodoPadre.getChildAt(k);
            if (!nodoActual.getUserObject().equals(archivoActual))
                return this.cargarObjeto(nodoPadre, archivoActual, k);
            iteradorListaArchivos+= 1;
        }
        int cantidadArchivos= archivos.size();
        if (cantidadArchivos == 1)
            return this.cargarObjeto(nodoPadre, archivos.get(0), cantidadNodos);
        else
            return this.cargarObjeto(nodoPadre, archivos.get(cantidadArchivos - 1), cantidadNodos);
    }
    
    public void eliminarNodo(DefaultMutableTreeNode nodo) {
        modelo.removeNodeFromParent(nodo);
    }
    
    public void organizarCarpetas(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        List<Carpeta> carpetas= carpetaPadre.getHijosCarpeta();
        int cantidadCarpetas= carpetas.size();
        for (int actual= 0; actual < cantidadCarpetas; actual++)
        {
            Carpeta carpetaActual= carpetas.get(actual);
            DefaultMutableTreeNode nodoActual= (DefaultMutableTreeNode) nodoPadre.getChildAt(actual);
            if (nodoActual.getUserObject().equals(carpetaActual))
            {
                nodoActual.setUserObject(carpetaActual);
                modelo.nodeChanged(nodoActual);
            }
            else
            {
                int posVieja= this.getIndice(nodoPadre, carpetaActual);
                DefaultMutableTreeNode nodoMover= (DefaultMutableTreeNode) nodoPadre.getChildAt(posVieja);
                modelo.removeNodeFromParent(nodoMover);
                modelo.insertNodeInto(nodoMover, nodoPadre, actual);
                nodoMover.setUserObject(carpetaActual);
                modelo.nodeChanged(nodoMover);
            }
        }
    }
    
    public void organizarClientes(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        List<Cliente> clientes= carpetaPadre.getHijosCliente();
        int cantidadCarpetas= carpetaPadre.getHijosCarpeta().size();
        int cantidadClientes= clientes.size();
        for (int actual= 0; actual < cantidadClientes; actual++)
        {
            Cliente clienteActual= clientes.get(actual);
            DefaultMutableTreeNode nodoActual= (DefaultMutableTreeNode) nodoPadre.getChildAt(actual + cantidadCarpetas);
            if (nodoActual.getUserObject().equals(clienteActual))
            {
                nodoActual.setUserObject(clienteActual);
                modelo.nodeChanged(nodoActual);
            }
            else
            {
                int posVieja= this.getIndice(nodoPadre, clienteActual);
                DefaultMutableTreeNode nodoMover= (DefaultMutableTreeNode) nodoPadre.getChildAt(posVieja);
                modelo.removeNodeFromParent(nodoMover);
                modelo.insertNodeInto(nodoMover, nodoPadre, actual + cantidadCarpetas);
                nodoMover.setUserObject(clienteActual);
                modelo.nodeChanged(nodoMover);
            }
        }
    }
    
    public void organizarArchivos(DefaultMutableTreeNode nodoPadre, Carpeta carpetaPadre)
    {
        List<Archivo> archivos= carpetaPadre.getHijosArchivo();
        int cantidadCarpetasYClientes= carpetaPadre.getHijosCarpeta().size() + carpetaPadre.getHijosCliente().size();
        int cantidadArchivos= archivos.size();
        for (int actual= 0; actual < cantidadArchivos; actual++)
        {
            Archivo archivoActual= archivos.get(actual);
            DefaultMutableTreeNode nodoActual= (DefaultMutableTreeNode) nodoPadre.getChildAt(actual +
                    cantidadCarpetasYClientes);
            if (nodoActual.getUserObject().equals(archivoActual))
            {
                nodoActual.setUserObject(archivoActual);
                modelo.nodeChanged(nodoActual);
            }
            else
            {
                int posVieja= this.getIndice(nodoPadre, archivoActual);
                DefaultMutableTreeNode nodoMover= (DefaultMutableTreeNode) nodoPadre.getChildAt(posVieja);
                modelo.removeNodeFromParent(nodoMover);
                modelo.insertNodeInto(nodoMover, nodoPadre, actual + cantidadCarpetasYClientes);
                nodoMover.setUserObject(archivoActual);
                modelo.nodeChanged(nodoMover);
            }
        }
    }
    
    private int getIndice(DefaultMutableTreeNode nodoPadre, Object elemento)
    {
        int cantidadNodos= nodoPadre.getChildCount();
        for (int indice= 0; indice < cantidadNodos; indice++)
        {
            DefaultMutableTreeNode hijo= (DefaultMutableTreeNode) nodoPadre.getChildAt(indice);
            if (hijo.getUserObject().equals(elemento))
                return indice;
        }
        return -1;
    }
}
